let LIFECYCLE_HOOKS = [
  "beforeCreate",
  "created",
  "beforeMount",
  "mounted",
  "beforeUpdate",
  "updated",
  "beforeDestroy",
  "destroyed",
];
function isPlainObject(obj) {
  return Object.prototype.toString.call(obj) === "[object Object]";
}
export function isObject(data) {
  //判断是否是对象
  if (typeof data !== "object" || data == null) {
    return false;
  }
  return true;
}

export function isReservedTag(tagName) {
  //判断是不是常规html标签
  // 定义常见标签
  let str =
    "html,body,base,head,link,meta,style,title," +
    "address,article,aside,footer,header,h1,h2,h3,h4,h5,h6,hgroup,nav,section," +
    "div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul," +
    "a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby," +
    "s,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video," +
    "embed,object,param,source,canvas,script,noscript,del,ins," +
    "caption,col,colgroup,table,thead,tbody,td,th,tr," +
    "button,datalist,fieldset,form,input,label,legend,meter,optgroup,option," +
    "output,progress,select,textarea," +
    "details,dialog,menu,menuitem,summary," +
    "content,element,shadow,template,blockquote,iframe,tfoot";
  let obj = {};
  str.split(",").forEach((tag) => {
    obj[tag] = true;
  });
  return obj[tagName];
}

function mergeHooks(parent, child) {
  if (child) {
    if (parent) {
      // 合并mixin钩子和组件钩子，并且mixin钩子在前先执行
      return parent.concat(child);
    } else {
      return [child];
    }
  } else {
    return parent;
  }
}
// 合并data
function mergeData(to = {}, from) {
  if (!from) return to;
  let key, toVal, fromVal;
  const keys = Object.keys(from);

  for (let i = 0; i < keys.length; i++) {
    key = keys[i];
    toVal = to[key];
    fromVal = from[key];
    if (!to[key]) {
      //将属性添加到to中
      to[key] = fromVal;
    } else if (
      toVal !== fromVal &&
      isPlainObject(toVal) &&
      isPlainObject(fromVal)
    ) {
      mergeData(toVal, fromVal);
    }
  }
  return to;
}

let strage = {};
LIFECYCLE_HOOKS.forEach((item) => {
  strage[item] = mergeHooks;
});

strage.data = function (parentVal, childVal) {
  return mergeData(
    typeof childVal === "function" ? childVal.call(this, this) : childVal,
    typeof parentVal === "function" ? parentVal.call(this, this) : parentVal
  );
};

strage.props =
strage.methods =
strage.inject =
strage.computed =
    function (parentVal, childVal) {
      if (!parentVal) return childVal;
      let ret = Object.create(null);
      ret = { ...ret, ...parentVal }
      if (childVal) (ret = { ...ret, ...childVal });
      return ret;
    };

strage.watch = function (parentVal, childVal) {
  if (!parentVal) return childVal
  let ret = {...{}, ...parentVal}
  // extend(ret, parentVal)
  for (const key in childVal) {
    let parent = ret[key]
    const child = childVal[key]
    if (parent && !Array.isArray(parent)) {
      parent = [parent]
    }
    ret[key] = parent ? parent.concat(child) : Array.isArray(child) ? child : [child]
  }
  return ret
}
export function mergeOptions(parent = {}, child) {
  let options = {};

  for (let key in parent) {
    mergeField(key);
  }

  for (let key in child) {
    if (!parent.hasOwnProperty(key)) {
      mergeField(key);
    }
  }

  function mergeField(key) {
    // 生命周期选项
    if (strage[key]) {
      // options[key] = mergeHooks(parent[key], child[key])
      options[key] = strage[key](parent[key], child[key]);
    } else {
      // 其他选项，mixin里面的深度覆盖组件内部的
      options[key] = child[key] ? child[key] : parent[key];
    }
  }

  return options;
}
